Use case: Synchronization between two processes

This use case shows how two processes synchronize on the same hardware semaphore. One process owns the semaphore first, while the second one waits for its release through interrupt notification.

Sequence diagram

Synchronization Between Two Processes

@startuml

participant "Process 1" as App1
participant "Process 2" as App2
participant "HSEM Driver" as HSEM
participant "NVIC" as NVIC
participant "HW" as HW

group Enable interruption
App2 -> HSEM: HAL_HSEM_ActivateNotification()
end

group Take the hardware semaphore
App1 -> HSEM: HAL_HSEM_Take()
note right of HSEM
The hardware semaphore is taken by Process 1
end note
end

group Release the hardware semaphore
App1 -> HSEM: HAL_HSEM_Release()
HW -> NVIC: Interrupt
NVIC -> HSEM: HAL_HSEM_IRQHandler()
HSEM --> App2: HAL_HSEM_FreeCallback()
note right of NVIC
The hardware semaphore is released
end note
end

group Disable interruption
App2 -> HSEM: HAL_HSEM_DeactivateNotification()
end

group Take the hardware semaphore
App2 -> HSEM: HAL_HSEM_Take()
note right of HSEM
The hardware semaphore is taken by User Process 2
end note
end

group Release the hardware semaphore
App2 -> HSEM: HAL_HSEM_Release()
end


@enduml

Code snippet

Process

HAL1

HAL2

Process 1

#define HSEM_PROCESS_1  12U
#define HSEM_ID  0U /* HW semaphore 0 */

/* HSEM Clock Enable */
__HAL_RCC_HSEM_CLK_ENABLE();

/* Take semaphore 0 with Process 1 */
HAL_HSEM_Take(HSEM_ID, HSEM_PROCESS_1);

/* Release semaphore 0 with Process 1 */
HAL_HSEM_Release(HSEM_ID, HSEM_PROCESS_1);
#define HSEM_PROCESS_1  12U


/* HSEM Clock Enable */
HAL_RCC_HSEM_EnableClock();

/* Take semaphore 0 with Process 1 */
HAL_HSEM_Take(HAL_HSEM_0, HSEM_PROCESS_1);

/* Release semaphore 0 with Process 1 */
HAL_HSEM_Release(HAL_HSEM_0, HSEM_PROCESS_1);

Process 2

#define HSEM_PROCESS_2  13U
#define HSEM_ID  0U /* HW semaphore 0 */
static volatile uint32_t hsem_released = 0U;

/* HSEM Clock Enable */
__HAL_RCC_HSEM_CLK_ENABLE();

/* Enable the interruption for semaphore 0 with Process 2 */
HAL_HSEM_ActivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID));

/* Wait until the semaphore release is notified */
while (hsem_released == 0U)
{
}

/* Deactivate HSEM notification */
HAL_HSEM_DeactivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID));

/* Take semaphore 0 with Process 2 */
HAL_HSEM_Take(HSEM_ID, HSEM_PROCESS_2);

/* Release semaphore 0 with Process 2 */
HAL_HSEM_Release(HSEM_ID, HSEM_PROCESS_2);

void HSEM_IRQHandler(void)
{
    HAL_HSEM_IRQHandler();
}

void HAL_HSEM_FreeCallback(uint32_t SemMask)
{
    if ((SemMask & __HAL_HSEM_SEMID_TO_MASK(HSEM_ID)) != 0U)
    {
        hsem_released = 1U;
    }
}
#define HSEM_PROCESS_2  13U
static volatile uint32_t hsem_released = 0U;


/* HSEM Clock Enable */
HAL_RCC_HSEM_EnableClock();

/* Enable the interruption for semaphore 0 with Process 2 */
HAL_HSEM_EnableFreeNotificationIT(HAL_HSEM_0);

/* Wait until the semaphore release is notified */
while (hsem_released == 0U)
{
}

/* Deactivate HSEM notification */
HAL_HSEM_DisableFreeNotificationIT(HAL_HSEM_0);

/* Take semaphore 0 with Process 2 */
HAL_HSEM_Take(HAL_HSEM_0, HSEM_PROCESS_2);

/* Release semaphore 0 with Process 2 */
HAL_HSEM_Release(HAL_HSEM_0, HSEM_PROCESS_2);

void HSEM_S_IRQHandler(void)
{
    HAL_HSEM_IRQHandler();
}

void HAL_HSEM_FreeCallback(hal_hsem_t semaphore)
{
    if (semaphore == HAL_HSEM_0)
    {
        hsem_released = 1U;
    }
}